from xml.sax import xmlreader, make_parser, handler
#from handlers import Simple_handler

import StringIO

def get_set (*args):
    return [s for s in args if s is not None ]

def difference (l1, l2):
    return filter (lambda el, l = l2 : el not in l, l1) 

def my_min (l, key):
    if not l:
        return None
    ans = l[0]
    for el in l:
        if key (el) < key(ans):
            ans = el
    return ans

class Configuration(handler.ContentHandler):
    BUS, QUEUE, JMS, FACTORY, MQ, DATASOURCE, SPECIFICATION, JAAS, APPLICATION, DESTINATION, JAASs, JDBC_ADAPTER, BINDING, BINDINGS = range (14)

    MODES = (("create_bus", [BUS]), 
             ("create_bus_queue", [BUS, QUEUE]), 
             ("create_jms_queue", [JMS, QUEUE]), 
             ("create_jms_as", [JMS, SPECIFICATION, QUEUE]), 
             ("create_jms_factory", [FACTORY, JMS]), 
             ("create_mq_queue", [MQ, QUEUE]), 
             ("create_datasource", [DATASOURCE]), 
             ("create_mq_factory", [MQ, FACTORY]),
             ("create_authentification_alias", [JAAS, JAASs]),
             ("deploy_application", [APPLICATION]),
             ("create_jdbc_adapter_as", [SPECIFICATION, JDBC_ADAPTER]),
             ("application_destination", [DESTINATION, APPLICATION]),
             ("string_binding", [BINDING, BINDINGS]))

    modes = {"bus" : BUS, "queue" : QUEUE, "factory" : FACTORY, "MQ" : MQ, "datasource" : DATASOURCE, "jms" : JMS, "specification" : SPECIFICATION, "JAAS" : JAAS, "application" : APPLICATION, "destination" : DESTINATION, "JAASs" : JAASs, "JDBCAdapter" : JDBC_ADAPTER, "binding" : BINDING, "bindings" : BINDINGS}
    mode = []
    chars = ""
    cur_element = ""
    params = {}
    attrs = {}

    def __init__(self, config_name, handler):
        self.text, self.handler = open(config_name).read(), handler
    def parse (self):
        source = xmlreader.InputSource ()
        source.setByteStream (StringIO.StringIO(self.text))
        parser = make_parser ()
        parser.setContentHandler (self)
        parser.setFeature (handler.feature_namespaces, 0)
        parser.parse (source)
        print "parser", parser
    def startElement (self, name, attrs):
        self.attrs[name] = attrs
        self.mode = self.mode + get_set(self.modes.get(name))
    def endElement (self, name, *a):
        if name == "server":
            self.handler.server = self.chars
        if name == "node":
            self.handler.node = self.chars
        self.params[name] = self.chars
        for key in self.attrs[name].getNames():
            self.params[key] = self.attrs[name][key]
        if name in self.modes.keys():
#            func = map(lambda a : a[0], filter (lambda sample : sample[1].issubset(self.mode), self.MODES))
            is_subset = lambda small, big : len(filter (lambda s : s == 0, map (lambda s, big=big : s in big, small))) == 0
            m = filter (lambda sample, mode = self.mode, modes = self.modes, MODES = self.MODES, is_subset = is_subset, name=name : is_subset(sample[1], mode) and modes[name] in sample[1], self.MODES)
            if m :
                func = [my_min(m, lambda sample, mode = self.mode : len(difference(mode, sample[1])) )[0]]
                print func
                map (lambda f, handler = self.handler, params = self.params, this=self : getattr(handler, f)(**params), func)
            self.params["action"] = ""
        self.mode = filter (lambda s, modes = self.modes, mode = self.mode, name = name : s not in get_set(modes.get(name)), self.mode)
#        for el in get_set(self.modes.get(name)):
 #           while el in self.mode:
  #              self.mode.remove(el)
        self.chars = ""
        self.attrs[name] = None
        
    def characters (self, content):
        self.chars = (self.chars + content).strip()
